#![allow(unused)]

use std::collections::HashMap;
use std::fmt;
use std::sync::Arc;

use serde_json;
use thiserror::Error;

use crate::asset;
use crate::network;
use crate::prelude::*;
use crate::resource;

pub enum IntentTy {
    Transfer,
}

/// Data for an active intent.
pub struct IntentData {
    ty: IntentTy,
    state: serde_json::Value,
}

pub enum ParamTy {
    Address,
    Amount,
    Asset,
    Bytes,
}

pub struct ParamTemplate {
    params: HashMap<String, ParamTy>,
}

#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
pub struct IntentId(u64);

impl From<u64> for IntentId {
    fn from(v: u64) -> Self {
        Self(v)
    }
}

pub struct IntentConfig {
    params: HashMap<String, ParamTy>,
}

#[derive(Clone)]
pub enum ResFilter {
    Funds(network::Chain, asset::Asset, asset::Amount),
}

#[derive(Clone)]
pub struct FilterConfig {
    filters: Vec<ResFilter>,
}

impl fmt::Debug for FilterConfig {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_fmt(format_args!("[filter_config({})]", self.filters.len()))
    }
}

#[derive(Debug, Error)]
pub enum IntentError {
    #[error("missing parameter '{0}'")]
    MissingParam(String),

    #[error("missing resources")]
    MissingResource(FilterConfig),
}

/// Low level intent validator and executor trait.
#[async_trait]
pub trait Executor {
    /// Checks if the intent can be executed on top of the supplied inventory.
    fn check_intent(
        &self,
        inv: &resource::Inventory,
        cfg: &IntentConfig,
    ) -> Result<(), IntentError>;
}

pub type ExecutorRef = Arc<dyn Executor>;
